//
// Mouse Gesture Recognizer
// (c) Robert Hahn / HTW Dresden
//
// TrainingPattern.cs
// ------------------
// Contains training pattern related interfaces and classes.
//

using System;
using System.Xml;
using System.Collections;
using System.Globalization;
using System.Threading;

using System.Diagnostics;

namespace CNeural
{
	/// <summary>
	/// Represents a single training pattern with input and output for a 
	/// neural network.
	/// </summary>
	public interface INeuralPattern
	{
		float[] Input { get; }
        float[] Output { get; }	
	}

	
	/// <summary>
	/// Summary description for NeuralPattern.
	/// </summary>
	public class NeuralPattern : INeuralPattern
	{
		protected float[] input;
		protected float[] output;

		public float[] Input 
		{
			get 
			{ 
				return this.input; 
			}
		}

		public float[] Output 
		{
			get 
			{ 
				return this.output; 
			}
		}
		
		public NeuralPattern(double[] input, double[] output)
		{
			this.input = new float[input.GetLength(0)];
			for(int i = 0; i < input.GetLength(0); i++)
			{
				input[i] = (double)input[i];
			}
			this.output = new float[output.GetLength(0)];
			for(int i = 0; i < output.GetLength(0); i++)
			{
				output[i] = (double)output[i];
			}

			
		}

		public NeuralPattern(float[] input, float[] output)
		{
			this.input = input;
			this.output = output;
		}
		public NeuralPattern(ArrayList inpArr, ArrayList outArr)
		{
			this.input = new float[inpArr.Count];
			for(int i = 0; i < inpArr.Count; i++)
			{
				input[i] = Convert.ToSingle(inpArr[i]);
			}
			this.output = new float[outArr.Count];
			for(int i = 0; i < outArr.Count; i++)
			{
				output[i] = Convert.ToSingle(outArr[i]);
			}
		
		}
	}


	/// <summary>
	/// Represents a typed array list for training patterns.
	/// </summary>
	[Serializable]
	public class NeuralPatternList : ArrayList 
	{
		/// <summary>
		/// Indexer.
		/// </summary>
		public new INeuralPattern this[int index] 
		{
			get { return base[index] as INeuralPattern; }
			set { base[index] = value; }
		}
		
		/// <summary>
		/// Adds a new training pattern to the list.
		/// </summary>
		/// <param name="pattern">The pattern to add.</param>
		public void Add(INeuralPattern pattern) 
		{
			base.Add(pattern);
		}

		public static NeuralPatternList Load(string filename)
		{
			XmlTextReader reader = new XmlTextReader(filename);
			XmlDocument doc = new XmlDocument();
			
			int patternCount = 0;
			int inputCount = 0;
			int outputCount = 0;
			
			INeuralPattern p;
			NeuralPatternList pl = new NeuralPatternList();
			try 
			{
				doc.Load(reader);
				patternCount = Int32.Parse(doc.DocumentElement.Attributes["number"].Value);
				inputCount = Int32.Parse(doc.DocumentElement.Attributes["inputs"].Value);
				outputCount = Int32.Parse(doc.DocumentElement.Attributes["outputs"].Value);
				
				foreach (XmlNode patternNode in doc.DocumentElement.ChildNodes) 
				{
					ArrayList inputValues = new ArrayList();
					foreach (XmlNode valueNode in patternNode["input"].ChildNodes) 
					{
						inputValues.Add(Double.Parse(valueNode.Value));
					}
					
					ArrayList outputValues = new ArrayList();
					foreach (XmlNode valueNode in patternNode["output"].ChildNodes) 
					{
						outputValues.Add(Double.Parse(valueNode.Value));
					}
					p = new NeuralPattern((double[])inputValues.ToArray(typeof(double)), 
						(double[])outputValues.ToArray(typeof(double)));
					pl.Add(p);
				}
			}
			catch (Exception exc) 
			{
				Debug.WriteLine(exc.Message);
				
			}
			reader.Close();
			return pl;
		}
	}
}
